package com.hongpu.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hongpu.config.SecurityContextUtil;
import com.hongpu.domain.SysUser;
import com.hongpu.domain.SysUserRole;
import com.hongpu.dto.ResetPasswordDto;
import com.hongpu.dto.SysUserDetailDto;
import com.hongpu.dto.TenantAdminDto;
import com.hongpu.mapper.SysUserMapper;
import com.hongpu.service.SysRoleMenuService;
import com.hongpu.service.SysUserRoleService;
import com.hongpu.service.SysUserService;
import com.hongpu.utils.ResultDto;
import com.hongpu.vo.SysMenuVo;
import com.hongpu.vo.SysRoleVo;
import com.hongpu.vo.SysUserDetailVo;
import com.hongpu.vo.TenantAdminVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
* @author Michael zhang
* @description 针对表【sys_user(系统用户表)】的数据库操作Service实现
* @createDate 2025-05-13 14:15:24
*/
@Service
@Slf4j
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser>
    implements SysUserService {
    @Autowired
    SysUserMapper baseMapper;
    @Autowired
    SysUserRoleService sysUserRoleService;
    @Autowired
    SysRoleMenuService sysRoleMenuService;
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    PasswordEncoder passwordEncoder;

    private static final String TENANT_ADMIN_ROLE = "租户管理员";

    /**
     * 新增
     *
     * @param sysUser
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDto ignoreTenantIdAndAddTenantAdmin(SysUser sysUser) {
        try {
            String account = sysUser.getAccount();
            Long userIdByUserAccount = getUserIdByUserAccount(account);
            if(userIdByUserAccount != null){
                return ResultDto.fail("该账号"+account+"在系统中已经存在，请更换其他账号添加");
            }
            Long tenantId = sysUser.getTenantId();
            String encryptPassword = passwordEncoder.encode(sysUser.getPassword());
            sysUser.setPassword(encryptPassword);
            baseMapper.ignoreTenantIdAndAddTenantAdmin(sysUser);
            // 配置角色信息
            Long roleId = baseMapper.getTenantAdminRoleId();
            baseMapper.addUserRole(new SysUserRole().setUserId(sysUser.getId()).setRoleId(roleId).setTenantId(tenantId));
            return ResultDto.ok();
        } catch (Exception e) {
            e.printStackTrace();
            log.info(e.getLocalizedMessage());
           return ResultDto.fail(e.getLocalizedMessage());
        }
    }



    /**
     * 忽略租户id的前提下，查询用户信息
     *
     * @param userId
     */
    @Override
    public String ignoreTenantIdAndGetSysUserByUserId(Long userId) {
        return baseMapper.ignoreTenantIdAndGetSysUserByUserId(userId);
    }
    /**
     * 忽略租户id的前提下，删除用户信息
     *
     * @param userId
     */
    @Override
    public boolean ignoreTenantIdAndDeleteSysUserByUserId(Long userId) {
        Long updateBy = SecurityContextUtil.getUserId();
        return baseMapper.ignoreTenantIdAndDeleteSysUserByUserId(userId,updateBy);
    }

    /**
     * 忽略租户id的前提下，启用租户信息
     *
     * @param userId
     */
    @Override
    public boolean ignoreTenantIdAndActiveSysUserByUserId(Long userId) {
        Long updateBy = SecurityContextUtil.getUserId();
        return baseMapper.ignoreTenantIdAndActiveSysUserByUserId(userId,updateBy);
    }

    /**
     * 忽略租户id的前提下，查询租户信息
     *
     * @param userId
     */
    @Override
    public TenantAdminVo ignoreTenantIdAndDetailSysUserByUserId(Long userId) {
        return baseMapper.ignoreTenantIdAndDetailSysUserByUserId(userId);
    }

    /**
     * 忽略租户id的前提下，查询租户分页
     *
     * @param tenantAdminDto
     */
    @Override
    public IPage<TenantAdminVo> ignoreTenantIdAndPageTenantAdmin(TenantAdminDto tenantAdminDto) {
        try {
            IPage page = new Page(tenantAdminDto.getCurrent(), tenantAdminDto.getSize());
            return baseMapper.ignoreTenantIdAndPageTenantAdmin(page,tenantAdminDto);
        } catch (Exception e) {
            log.info(e.getLocalizedMessage());
            return new Page<>(tenantAdminDto.getCurrent(), tenantAdminDto.getSize());
        }
    }

    /**
     * 忽略租户id的前提下，修改租户信息
     *
     * @param sysUser
     */
    @Override
    public boolean ignoreTenantIdAndUpdateTenantAdmin(TenantAdminDto tenantAdminDto) {
        tenantAdminDto.setUpdateBy(SecurityContextUtil.getUserId());
        return baseMapper.ignoreTenantIdAndUpdateTenantAdmin(tenantAdminDto);
    }

    /**
     * 忽略租户id的前提下，修改租户管理员密码
     *
     * @param tenantAdminDto
     */
    @Override
    public boolean ignoreTenantIdAndUpdateTenantAdminPassword(TenantAdminDto tenantAdminDto) {
        tenantAdminDto.setUpdateBy(SecurityContextUtil.getUserId());
        String encryptPassword = passwordEncoder.encode(tenantAdminDto.getPassword());
        tenantAdminDto.setPassword(encryptPassword);
        return baseMapper.ignoreTenantIdAndUpdateTenantAdminPassword(tenantAdminDto);
    }

    /**
     * 忽略租户id的前提下，根据传递的租户ID将租户ID下所有用户 deleted 字段设置为1。适用场景：租户停用或暂停状态下，该租户下所有用户不能登录
     *
     * @param tenantId
     */
    @Override
    public boolean ignoreTenantIdAndUpdateStatusDeleted(Long tenantId) {
        return baseMapper.ignoreTenantIdAndUpdateStatusDeleted(tenantId,SecurityContextUtil.getUserId());
    }

    /**
     * 忽略租户id的前提下，根据传递的租户ID将该租户ID下所有用户 deleted 字段设置为0。适用场景：租户启用下状态，该租户下所有用户都可以登录
     *
     * @param tenantId
     */
    @Override
    public boolean ignoreTenantIdAndUpdateStatusActive(Long tenantId) {
        return baseMapper.ignoreTenantIdAndUpdateStatusActive(tenantId,SecurityContextUtil.getUserId());
    }

    /**
     * 租户管理员添加普通用户
     *
     * @param sysUser
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDto add(SysUser sysUser) {
        try {
            String encryptPassword = passwordEncoder.encode(sysUser.getPassword());
            sysUser.setPassword(encryptPassword);
            save(sysUser);
            Long userId = sysUser.getId();
            List<Long> roleIds = sysUser.getRoleIds();
            for (Long roleId : roleIds) {
                sysUserRoleService.save(new SysUserRole().setUserId(userId).setRoleId(roleId));
            }
            return ResultDto.ok();
        } catch (Exception e) {
            e.printStackTrace();
            return ResultDto.fail(e.getLocalizedMessage());
        }
    }
    /**
     * 租户的管理员删除普通用户
     */
    @Override
    public ResultDto deleteUserById(Long id) {
        try {
            // 1、 检查该用户的角色是不是租户管理员，如果是，则不允许删除。
            List<String> roleNames = baseMapper.getRoleNamesByUserId(id,SecurityContextUtil.getTenantId());
            if(roleNames.contains(TENANT_ADMIN_ROLE)){
                return ResultDto.warning("租户管理员不能删除");
            }
            // 2、执行删除
            removeById(id,true);
            return ResultDto.ok();
        } catch (Exception e) {
            log.info(e.getLocalizedMessage());
            return ResultDto.fail(e.getLocalizedMessage());
        }
    }

    /**
     * 租户的管理员启用普通用户
     *
     * @param id
     */
    @Override
    public ResultDto activeById(Long id) {
        try{
            boolean update = baseMapper.activeById(id,SecurityContextUtil.getUserId());
            if (!update) {
                return ResultDto.fail();
            }
            return ResultDto.ok();
        } catch (Exception e) {
            e.printStackTrace();
            return ResultDto.fail(e.getLocalizedMessage());
        }

    }

    /**
     * 租户管理员查询普通用户分页
     *
     * @param sysUserDetailDto
     */
    @Override
    public ResultDto page(SysUserDetailDto sysUserDetailDto) {
        try {
            IPage  page = new Page(sysUserDetailDto.getCurrent(), sysUserDetailDto.getSize());
            sysUserDetailDto.setTenantId(SecurityContextUtil.getTenantId());
            IPage<SysUserDetailVo> selectPage = baseMapper.selectSysUserDetailVoPage(page, sysUserDetailDto);
            return ResultDto.ok(selectPage);
        } catch (Exception e) {
            e.printStackTrace();
            return ResultDto.fail(e.getLocalizedMessage());
        }
    }

    /**
     * 根据用户名查询用户信息
     *
     * @param username
     * @return
     */
    @Override
    public SysUser getSysUserByUseraccount(String account) {
        return baseMapper.ignoreTenantIdAndGetSysUserByUseraccount(account);
    }

    /**
     * 根据用户名查询用户ID
     *
     * @param username
     */
    @Override
    public Long getUserIdByUserAccount(String account) {
        return getSysUserByUseraccount(account).getId();
    }

    /**
     * 根据用户ID查询角色ID
     *
     * @param userId
     */
    @Override
    public List<SysRoleVo> getRoleIdsByUserId(Long userId) {
        return sysUserRoleService.getRoleIdsByUserId(userId);
    }

    /**
     * 根据角色ID查询权限ID
     *
     * @param roleIds
     */
    @Override
    public List<SysMenuVo> getSysMenusByRoleId(List<SysRoleVo> roleIds) {
        return sysRoleMenuService.queryMenuTreeByRoldIds(roleIds);
    }

    /**
     * 登录成功后，进入首页，前端获取用户信息
     */
    @Override
    public ResultDto getUserInfo() {
        try {
            String userAccount = SecurityContextUtil.getUserAccount();
            String redisKey = String.format("auth:user:account:%s",userAccount);
            String info = stringRedisTemplate.opsForValue().get(redisKey);
            SysUser sysUser = JSONObject.parseObject(info, SysUser.class);
            return ResultDto.ok(sysUser);
        } catch (Exception e) {
            return ResultDto.fail("获取用户信息失败");
        }
    }

    /**
     * 租户管理员重置用户密码
     *
     * @param resetPasswordDto
     */
    @Override
    public ResultDto resetPassword(ResetPasswordDto resetPasswordDto) {
      try {
          String encryptPassword = passwordEncoder.encode(resetPasswordDto.getPassword());
          boolean update = update(new UpdateWrapper<SysUser>().eq("id", resetPasswordDto.getId()).set("password", encryptPassword));
          return update ? ResultDto.ok() : ResultDto.fail();
      } catch (Exception e) {
          return ResultDto.fail("重置密码失败");
      }
    }

    /**
     * 租户管理员根据用户ID修改用户详情
     *
     * @param sysUserDetailDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDto update(SysUserDetailDto sysUserDetailDto) {
       try {
           SysUser sysUser = new SysUser();
           BeanUtils.copyProperties(sysUserDetailDto,sysUser);
           updateById(sysUser);
           Long userId = sysUserDetailDto.getId();
           List<Long> roleIds = sysUserDetailDto.getRoleIds();
            // 根据用户ID删除所有角色后重新添加角色
           sysUserRoleService.deleteRoleIdsByUserId(userId);
           for (Long roleId : roleIds) {
               sysUserRoleService.save(new SysUserRole().setUserId(userId).setRoleId(roleId));
           }
           return ResultDto.ok();
       } catch (Exception e) {
           e.printStackTrace();
           return ResultDto.fail(e.getLocalizedMessage());
       }
    }

    /**
     * 租户管理员根据用户ID查询用户详情
     *
     * @param id
     */
    @Override
    public ResultDto detail(Long id) {
        try {
            SysUser sysUser = getById(id);
            if(sysUser == null){
                return ResultDto.ok(new SysUserDetailVo());
            }else {
                // 查询用户角色ID集合
                List<SysRoleVo> sysRoleVos = sysUserRoleService.getRoleIdsByUserId(id);
                SysUserDetailVo sysUserDetailVo = new SysUserDetailVo();
                BeanUtils.copyProperties(sysUser,sysUserDetailVo);
                sysUserDetailVo.setRoleIds(sysRoleVos.stream().map(SysRoleVo::getId).collect(Collectors.toList()));
                return ResultDto.ok(sysUserDetailVo);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResultDto.fail(e.getLocalizedMessage());
        }
    }

    /**
     * 超级管理员在租户下新增租户管理员时，根据选择的租户ID查询该租户下是否有管理员用户
     *
     * @param tenantId
     */
    @Override
    public ResultDto getTenantAdminByTenantId(Long tenantId) {
        SysUser sysUser = baseMapper.getTenantAdminByTenantId(tenantId);
        return sysUser == null ? ResultDto.ok(false) : ResultDto.ok(sysUser);
    }
}




